
/* GCSx
** ANIMGROUPPAINT.H
**
** Animation group editing
*/

/*****************************************************************************
** Copyright (C) 2003-2006 Janson
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
*****************************************************************************/

#ifndef __GCSx_ANIMGROUPPAINT_H_
#define __GCSx_ANIMGROUPPAINT_H_

class AnimGroupPaintTools : public Dialog {
private:
    class FrameWindow* myFrame;
    class ToolSelect* toolSelect;
    class ToolSelect* outlineSelect;
    class ImageSelect* imagebar;
    class AnimGroupPaint* paintArea;

    enum {        
        // For tool popup selections
        TOOLSELECT_NUM_TOOLS = 3,
        // Outline options selection
        TOOLSELECT_NUM_OUTLINE = 3,
    };
    
    static const ToolSelect::ToolIconStruct toolIcons[TOOLSELECT_NUM_TOOLS];
    static const ToolSelect::ToolIconStruct outlineIcons[TOOLSELECT_NUM_OUTLINE];
    
    // Used to help resize preview area- this is
    // our height if preview is 0 pixels high
    int minHeight;
    
public:
    enum {
        // Color select
        ID_COLOR = 1,
        
        // Individual buttons
        ID_TOOLL,
        ID_TOOLR,
        ID_COPY,
        ID_PASTE,
        ID_TOP,
        ID_UP,
        ID_DOWN,
        ID_BOTTOM,
        
        // Setting buttons
        ID_OUTLINE,
        
        // Animation name
        ID_NAMELABEL,
        ID_NAME,
        
        // Tileset
        ID_TILESETLABEL,
        ID_TILESET,
        
        // Preview
        ID_PREVIEW,
    };

    int* toolLPtr;
    int* toolRPtr;
    int* outlinePtr;
    std::string* animNamePtr;
    class TileSetEdit** tilesetPtr;
    int selectedTileset;
    
    class WListBox* tilesetList;

    AnimGroupPaintTools(class AnimGroupPaint* tPaintArea, class ImageSelect* mImagebar, int* toolL, int* toolR, int* outline, std::string* animName, class TileSetEdit** tileset);
    ~AnimGroupPaintTools();

    // Creates a FrameWindow and returns, does not add self to desktop (use ->show() to do that)
    class FrameWindow* createWindowed();

    int event(int hasFocus, const SDL_Event* event);
    void resize(int newWidth, int newHeight, int newViewWidth = -1, int newViewHeight = -1, int fromParent = 0);
    void childModified(Window* modified);
    void previewRedraw();
    int wantsToBeDeleted() const;
    WindowSort windowSort() const;
};

class AnimGroupPaint : public Window {
private:
    class FrameWindow* myFrame;
    AnimGroupPaintTools* tools;
    ImageSelect* imagebar;
    class ColorSelect* colorbar;

    int hover;
    int lastMouseX;
    int lastMouseY;

    int toolL;
    int toolR;
    int outline;
    int enableGrid;
    
    AnimGroupEdit* animgroup;
    ColorStore colors;
    class TileSetEdit* tileset; // Can't be const

    // Storage for editing
    AnimSequence anim;
    // @TODO: separate ptr to current frame for speed?
    
    int seqId; // Which sequence and which frame of that seq we're editing
    int frameId;
    int frameCount; // Total # frames in current sequence

    int cursorComp; // Which component is the cursor on (<0 for no cursor)
    std::set<int> selected; // Which components are selected
    std::set<int> backupSelected;
    Rect selectRect;
    Rect backupSelectRect;

    int haveFocus;
    int partialFocus;
    
    int toolActive;
    int toolCtrl;
    int toolAlt;
    int toolStartX; // Starting coordinates for a component/selection rect drag
    int toolStartY;
    int toolLastX; // Last used coordinates during a drag
    int toolLastY;
    
    // (doesn't set any sort of dirty)
    void refreshData();
    void applyData();
    
    void refreshName();
    void applyName();

    void startTool(int x, int y, int button);
    void startToolSelectionDrag(int x, int y);
    void modifyTool(); // Call if CTRL/ALT changes
    void dragTool(int x, int y, int firstTime = 0, int lastTime = 0);
    void finishTool();
    void cancelTool();
    
    // Dirty range
    Rect dirtyRange;

    // Set partial dirty by area (pixel) specifically allows ranges outside maximums
    void setDirtyBox(int x1, int y1, int x2, int y2);
    void setDirtyRect(const Rect& rect);
    // Set partial dirty by component
    void setDirtyComp(int subid);

    // Undo wrappers
    void undoStore() throw_Undo; // Simply stores entire frame
    void undoStoreSelect() throw_Undo;

    // Selection tool- clips; coordinates in pixels
    void selectViaRect(int x1, int y1, int x2, int y2, int set);

    // Clear selection
    void clearSelection(int storeUndo = 1) throw_Undo;
    // Copy selection to clipboard
    void copySelection();
    // Paste clipboard as a new selection; Stores undo
    void pasteSelection() throw_Undo;
    // Delete selected items; Stores undo
    void deleteSelection() throw_Undo;
    // Returns true if a given pixel x/y is within a currently selected component
    int isInSelection(int x, int y) const;

    // Moves all selected items- doesn't store update or undo
    void moveSelection(int changeX, int changeY);
    
    void mousePointer();
    void mousePointer(int mouseX, int mouseY);
    void updateTitlebar();
    
    enum {
        // size of frame resize handle
        RESIZE_HANDLE_SIZE = 8,
    };

public:
    // Opens the window (animid is 1-based)
    AnimGroupPaint(AnimGroupEdit* myAnimGroup, int animId) throw_File;
    ~AnimGroupPaint();

    // Called by tool panel to tell us to refresh view
    void refresh();

    CommandSupport supportsCommand(int code) const;
    int event(int hasFocus, const SDL_Event* event);
    void display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset);
    WindowType windowType() const;
    void siblingModified(Window* modified);
    // @TODO: void undoNotify(int undoType, int undoItemId, int undoItemSubId, int uX, int uY, int uW, int uH);
    // (attempt to scroll to view an affected area)
};

#endif

